package com.harmony.pilot.generation.service.impl;

import com.harmony.pilot.common.dto.CodeContext;
import com.harmony.pilot.common.dto.GenerationRequest;
import com.harmony.pilot.common.dto.LLMRequest;
import com.harmony.pilot.generation.service.GenerationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.HashMap;
import java.util.Map;

/**
 * 代码生成服务实现
 */
@Slf4j
@Service
public class GenerationServiceImpl implements GenerationService {
    
    private final WebClient llmClient;
    private final WebClient dataClient;
    
    @Value("${generation.follow-standard}")
    private Boolean followStandard;
    
    public GenerationServiceImpl(@Value("${service.llm.url}") String llmUrl,
                                  @Value("${service.data.url}") String dataUrl) {
        this.llmClient = WebClient.builder().baseUrl(llmUrl).build();
        this.dataClient = WebClient.builder().baseUrl(dataUrl).build();
    }
    
    @Override
    public String generateCode(GenerationRequest request) {
        String type = request.getGenerationType();
        
        return switch (type) {
            case "function" -> generateFunction(request);
            case "class" -> generateClass(request);
            case "test" -> generateTest(request);
            case "comment" -> generateComment(request);
            default -> generateGeneric(request);
        };
    }
    
    @Override
    public String generateFunction(GenerationRequest request) {
        log.info("Generating function code");
        
        CodeContext context = request.getContext();
        String prompt = buildFunctionPrompt(request);
        
        LLMRequest llmRequest = LLMRequest.builder()
                .prompt(prompt)
                .systemPrompt(buildSystemPrompt("function"))
                .temperature(request.getTemperature())
                .maxTokens(request.getMaxLength())
                .build();
        
        return callLLM(llmRequest);
    }
    
    @Override
    public String generateClass(GenerationRequest request) {
        log.info("Generating class code");
        
        String prompt = buildClassPrompt(request);
        
        LLMRequest llmRequest = LLMRequest.builder()
                .prompt(prompt)
                .systemPrompt(buildSystemPrompt("class"))
                .temperature(request.getTemperature())
                .maxTokens(request.getMaxLength())
                .build();
        
        return callLLM(llmRequest);
    }
    
    @Override
    public String generateTest(GenerationRequest request) {
        log.info("Generating test code");
        
        String prompt = buildTestPrompt(request);
        
        LLMRequest llmRequest = LLMRequest.builder()
                .prompt(prompt)
                .systemPrompt(buildSystemPrompt("test"))
                .temperature(0.3) // Lower temperature for test generation
                .maxTokens(request.getMaxLength())
                .build();
        
        return callLLM(llmRequest);
    }
    
    @Override
    public String generateComment(GenerationRequest request) {
        log.info("Generating comment");
        
        String prompt = buildCommentPrompt(request);
        
        LLMRequest llmRequest = LLMRequest.builder()
                .prompt(prompt)
                .systemPrompt(buildSystemPrompt("comment"))
                .temperature(0.3)
                .maxTokens(300)
                .build();
        
        return callLLM(llmRequest);
    }
    
    private String generateGeneric(GenerationRequest request) {
        log.info("Generating generic code");
        
        LLMRequest llmRequest = LLMRequest.builder()
                .prompt(request.getPrompt())
                .systemPrompt(buildSystemPrompt("generic"))
                .temperature(request.getTemperature())
                .maxTokens(request.getMaxLength())
                .build();
        
        return callLLM(llmRequest);
    }
    
    /**
     * 构建函数生成的提示词
     */
    private String buildFunctionPrompt(GenerationRequest request) {
        CodeContext context = request.getContext();
        StringBuilder sb = new StringBuilder();
        
        sb.append("Generate a C++ function based on the following requirements:\n\n");
        sb.append("Requirements: ").append(request.getPrompt()).append("\n\n");
        
        if (context.getFilePath() != null) {
            sb.append("File: ").append(context.getFilePath()).append("\n");
        }
        
        if (context.getClassName() != null) {
            sb.append("Class: ").append(context.getClassName()).append("\n");
        }
        
        if (context.getNamespace() != null) {
            sb.append("Namespace: ").append(context.getNamespace()).append("\n");
        }
        
        if (context.getPrefix() != null && !context.getPrefix().isEmpty()) {
            sb.append("\nContext (previous code):\n");
            sb.append(context.getPrefix()).append("\n");
        }
        
        if (followStandard) {
            sb.append("\nPlease follow OpenHarmony C++ coding standards.\n");
        }
        
        sb.append("\nGenerate only the function code without explanations:");
        
        return sb.toString();
    }
    
    /**
     * 构建类生成的提示词
     */
    private String buildClassPrompt(GenerationRequest request) {
        CodeContext context = request.getContext();
        StringBuilder sb = new StringBuilder();
        
        sb.append("Generate a C++ class based on the following requirements:\n\n");
        sb.append("Requirements: ").append(request.getPrompt()).append("\n\n");
        
        if (context.getNamespace() != null) {
            sb.append("Namespace: ").append(context.getNamespace()).append("\n");
        }
        
        if (context.getIncludes() != null && !context.getIncludes().isEmpty()) {
            sb.append("Required includes: ").append(String.join(", ", context.getIncludes())).append("\n");
        }
        
        if (followStandard) {
            sb.append("\nPlease follow OpenHarmony C++ coding standards.\n");
        }
        
        sb.append("\nGenerate the complete class definition:");
        
        return sb.toString();
    }
    
    /**
     * 构建测试生成的提示词
     */
    private String buildTestPrompt(GenerationRequest request) {
        CodeContext context = request.getContext();
        StringBuilder sb = new StringBuilder();
        
        sb.append("Generate unit tests for the following C++ code:\n\n");
        
        if (context.getCode() != null) {
            sb.append("Code to test:\n");
            sb.append(context.getCode()).append("\n\n");
        }
        
        sb.append("Requirements: ").append(request.getPrompt()).append("\n\n");
        sb.append("Generate comprehensive unit tests using Google Test framework.");
        
        return sb.toString();
    }
    
    /**
     * 构建注释生成的提示词
     */
    private String buildCommentPrompt(GenerationRequest request) {
        CodeContext context = request.getContext();
        StringBuilder sb = new StringBuilder();
        
        sb.append("Generate documentation comment for the following C++ code:\n\n");
        
        if (context.getCode() != null) {
            sb.append(context.getCode()).append("\n\n");
        }
        
        sb.append("Generate a clear and concise Doxygen-style comment.");
        
        return sb.toString();
    }
    
    /**
     * 构建系统提示词
     */
    private String buildSystemPrompt(String type) {
        Map<String, String> prompts = new HashMap<>();
        
        prompts.put("function", 
            "You are an expert C++ developer specializing in OpenHarmony. " +
            "Generate clean, efficient, and well-structured function code.");
        
        prompts.put("class",
            "You are an expert C++ developer specializing in OpenHarmony. " +
            "Generate well-designed classes following SOLID principles and OpenHarmony conventions.");
        
        prompts.put("test",
            "You are an expert in C++ unit testing with Google Test. " +
            "Generate comprehensive and meaningful test cases.");
        
        prompts.put("comment",
            "You are a technical documentation expert. " +
            "Generate clear and professional code documentation.");
        
        prompts.put("generic",
            "You are an expert C++ developer for OpenHarmony. " +
            "Generate high-quality code following best practices.");
        
        return prompts.getOrDefault(type, prompts.get("generic"));
    }
    
    /**
     * 调用LLM服务
     */
    private String callLLM(LLMRequest request) {
        try {
            Map<String, Object> response = llmClient.post()
                    .uri("/llm/generate")
                    .bodyValue(request)
                    .retrieve()
                    .bodyToMono(Map.class)
                    .block();
            
            if (response != null && response.containsKey("code")) {
                return (String) response.get("code");
            }
            
            return "";
        } catch (Exception e) {
            log.error("Failed to call LLM service", e);
            throw new RuntimeException("Failed to generate code", e);
        }
    }
}

